package useraddress

import (
	"context"
	// "fmt"
	"strings"

	"mall/common/modelx"
	"mall/common/utils/pointy"
	"mall/service/user/model"
	"mall/service/user/rpc/internal/svc"
	"mall/service/user/rpc/types/user"

	// "github.com/sirupsen/logrus"
	"github.com/zeromicro/go-zero/core/logx"
)

type BackendGetUserAddressListLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewBackendGetUserAddressListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BackendGetUserAddressListLogic {
	return &BackendGetUserAddressListLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *BackendGetUserAddressListLogic) BackendGetUserAddressList(in *user.UserAddressListReq) (*user.UserAddressListResp, error) {
	// logrus.Info(fmt.Sprintf("UserAddressListReq: %+v", in))

	var orderBys []string
	if len(in.OrderBy) > 0 {
		for _, orderBy := range in.OrderBy {
			var order = " ASC"
			if orderBy.Order == "1" {
				order = " DESC"
			}
			if orderBy.Field == "id" {
				orderBys = append(orderBys, model.UserAddressColumns.UserAddressID+order)
			}
			if orderBy.Field == "createdAt" {
				orderBys = append(orderBys, model.UserAddressColumns.CreatedAt+order)
			}
			if orderBy.Field == "usedAt" {
				orderBys = append(orderBys, model.UserAddressColumns.LastUsedAt+order)
			}
		}
	}

	var stati string
	if len(in.FilterBy) > 0 {
		for _, filterBy := range in.FilterBy {
			if filterBy.Field == "status" {
				stati = filterBy.In
			}
		}
	}

	var page uint64
	var pageSize uint64
	var restricted bool
	filterMap := make(map[string]map[string][]any)
	resp := &user.UserAddressListResp{}
	if in.UserId != nil && *in.UserId > 0 {
		filterMap[model.UserAddressColumns.UserID] = map[string][]any{
			"equalTo": []any{*in.UserId},
		}
	}
	if in.Ids != nil {
		if vals := modelx.UniqueInterfaces(*in.Ids, 64); len(vals) == 0 {
			return resp, nil
		} else {
			filterMap[model.UserAddressColumns.UserAddressID] = map[string][]any{
				"in": vals,
			}
			restricted = true
		}
	}

	if !restricted {
		page = in.Page
		pageSize = in.PageSize
	}

	statusIn := modelx.UniqueInterfaces(stati, 32)
	statusMap := make(map[string][]any)
	if len(statusIn) > 0 {
		statusMap["in"] = statusIn
	}
	if in.Status != nil {
		statusMap["equalTo"] = []any{*in.Status}
	}
	filterMap[model.UserAddressColumns.Status] = statusMap

	if in.Consignee != nil {
		filterMap[model.UserAddressColumns.Consignee] = map[string][]any{
			"contain": []any{*in.Consignee},
		}
	}
	if in.Mobile != nil {
		filterMap[model.UserAddressColumns.Mobile] = map[string][]any{
			"contain": []any{*in.Mobile},
		}
	}

	var startTimeIn []any
	var endTimeIn []any
	if in.StartTime != nil && len(strings.TrimSpace(*in.StartTime)) > 0 {
		if startTime, err := modelx.ParseLocalDate(strings.TrimSpace(*in.StartTime)); err == nil {
			startTimeIn = append(startTimeIn, startTime)
		}
	}
	if in.EndTime != nil && len(strings.TrimSpace(*in.EndTime)) > 0 {
		if endTime, err := modelx.ParseLocalDate(strings.TrimSpace(*in.EndTime)); err == nil {
			endTimeIn = append(endTimeIn, endTime)
		}
	}
	createdAtMap := make(map[string][]any)
	if len(startTimeIn) > 0 {
		createdAtMap["moreThanOrEqualTo"] = startTimeIn
	}
	if len(endTimeIn) > 0 {
		createdAtMap["lessThan"] = endTimeIn
	}
	filterMap[model.UserAddressColumns.CreatedAt] = createdAtMap

	var orderBy string
	if len(orderBys) > 0 {
		orderBy = strings.Join(orderBys, ",")
	}
	res, count, err := l.svcCtx.UserAddress.GetList(l.ctx, model.M{
		"page":     page,
		"pageSize": pageSize,
		"orderBy":  orderBy,
	}, 1, filterMap)
	if err != nil {
		return nil, err
	}

	resp.Total = uint64(count)
	if len(res) > 0 {
		for _, v := range res {
			var isDefault uint32
			if v.IsDefault > 0 {
				isDefault = 1
			}

			var geographic []*user.UserMetaInfo
			if v.Geographic.Valid {
				if err = v.Geographic.Unmarshal(&geographic); err != nil {
					// logx.Infof("BackendGetUserAddressById: err %+v ", err)
					logx.Errorw("BackendGetUserAddressList Geographic.Unmarshal err", logx.Field("detail", err.Error()))
				}
			}

			resp.List = append(resp.List, &user.UserAddressInfo{
				Id:              pointy.GetPointer(v.UserAddressID),
				UserId:          pointy.GetPointer(v.UserID),
				Label:           pointy.GetPointer(v.Label),
				Consignee:       pointy.GetPointer(v.Consignee),
				Mobile:          pointy.GetPointer(v.Mobile),
				Province:        pointy.GetPointer(v.Province),
				City:            pointy.GetPointer(v.City),
				District:        pointy.GetPointer(v.District),
				Street:          pointy.GetPointer(v.Street),
				DetailedAddress: pointy.GetPointer(v.DetailedAddress),
				PostalCode:      pointy.GetPointer(v.PostalCode),
				RegionCode:      pointy.GetPointer(v.RegionCode),
				IsDefault:       pointy.GetPointer(isDefault),
				Status:          pointy.GetPointer(uint32(v.Status)),
				LastUsedAt:      pointy.GetPointer(modelx.FormatNullDotTime(v.LastUsedAt, "")),
				CreatedAt:       pointy.GetPointer(modelx.FormatTime(v.CreatedAt, "")),
				UpdatedAt:       pointy.GetPointer(modelx.FormatTime(v.UpdatedAt, "")),
				DeletedAt:       pointy.GetPointer(modelx.FormatNullDotTime(v.DeletedAt, "")),
				Geographic:      geographic,
			})
		}
	}

	return resp, nil
}
